home *** CD-ROM | disk | FTP | other *** search
/ Future Workshop / Future Workshop.iso / multimed / qtw111 / pviewer / framewnd.c < prev    next >
C/C++ Source or Header  |  1994-01-11  |  38KB  |  1,016 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // FrameWnd.c - Picture Viewer - QuickTime for Windows
  5. //
  6. //              Version 1.0
  7. //
  8. //              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13. // Includes
  14. // --------
  15. #define NOMINMAX
  16. #include <Windows.H>  // Required by Windows
  17. #include <commdlg.h>  // Header file for common dlgs
  18. #include <dlgs.h>     // Header file for common dlgs ids
  19. #include <cderr.h>    // Header file for error ids
  20. #include <memory.h>   // Needed for memset() function
  21. #include <shellapi.h> // Drag and drop stuff
  22.  
  23. #include <qtole.h> // Interface to qtole dll
  24.  
  25. #include "common.h" // Interface to common.c
  26.  
  27. #include "viewer.h"  // Interface to other *.c files
  28. #include "viewer.hr" // Defines used in *.rc files
  29. #include "picture.h" // Interface to other *.c files
  30.  
  31. // Message-Persistent Data
  32. // -----------------------
  33. static struct // Hungarian notation: g
  34.   { HWND      hwndClient;      // MDI client window
  35.     WORD      wNumPictures;    // Number of picture wnds
  36.     BOOL      bUserAbortPrint; // User abort print flag
  37.     HWND      hwndCancelPrt;   // Handle of print cancel dlg
  38.     HBITMAP   hAboutBitmap;    // Temp static storage of bitmap
  39.                                // displayed in about dialogs
  40.   } g;
  41.  
  42.  
  43. // Exported callback functions
  44. // ----------------------------
  45. BOOL __export CALLBACK AboutDlgProc       (HWND, UINT, WPARAM, LPARAM);
  46. BOOL __export CALLBACK CloseEnumProc      (HWND, LPARAM);
  47. BOOL __export CALLBACK PaletteEnumProc    (HWND, LPARAM);
  48. BOOL __export CALLBACK PrintCancelDlgProc (HWND, UINT, WPARAM, LPARAM);
  49. int  __export CALLBACK PrintAbortProc     (HDC, int);
  50. UINT __export CALLBACK PrintDlgHookProc   (HWND, UINT, WPARAM, LPARAM);
  51.  
  52. // Internal Function Declarations
  53. // ------------------------------
  54. static LONG NEAR ViewerFrameCreate       (HWND);
  55. static LONG NEAR ViewerFileCommands      (HWND, WPARAM, WORD);
  56. static LONG NEAR ViewerWindowCommands    (HWND, WPARAM, WORD);
  57. static LONG NEAR ViewerHelpCommands      (HWND, WPARAM, WORD);
  58. static LONG NEAR LaunchPictureWnd        (LPSTR, LPSTR);
  59. static VOID NEAR ViewerEnableMenus       (HWND, BOOL);
  60. static VOID NEAR TellUserCommonDlgError  (DWORD);
  61. static LONG NEAR ProcessDroppedFiles     (HWND, WPARAM );
  62. static VOID NEAR DestroyHelpInstance     (HWND);
  63.  
  64. // -----------------------------------------------------------------------
  65.  
  66.  
  67. // Function: ViewerFrameWndProc - Viewer Frame Window Procedure
  68. // --------------------------------------------------------------------
  69. // Parameters: As required by Microsoft Windows
  70. //
  71. // Returns:    Via DefFrameProc
  72. // --------------------------------------------------------------------
  73. LONG __export CALLBACK ViewerFrameWndProc
  74.     (HWND hwndFrame, UINT message, WPARAM wParam, LPARAM lParam)
  75.  
  76. {
  77.     WNDENUMPROC       lpfnEnumPictures; // -> callback funcion for
  78.                                         // enumeration of pictures
  79.     HWND              hwndPicture;      // Temp handle of active picture wnd
  80.     LPQTOLE_OLEDATA   lpOleData;        // -> to OLE data
  81.  
  82.  
  83.     switch( message ) {
  84.         case WM_CREATE:
  85.             return ViewerFrameCreate( hwndFrame );
  86.  
  87.         case WM_PALETTECHANGED:
  88.             if( g.wNumPictures &&
  89.                 ( lpfnEnumPictures = (WNDENUMPROC) MakeProcInstance
  90.                 ( (FARPROC) PaletteEnumProc, ViewerQueryInstance()))) {
  91.                 StoreCurrentSystemPalette( NULL );
  92.  
  93.                 // Tell the picture wnds to repaint themselves
  94.                 EnumChildWindows( g.hwndClient, lpfnEnumPictures,
  95.                     (LPARAM) wParam);
  96.                 FreeProcInstance( (FARPROC) lpfnEnumPictures );
  97.             }
  98.  
  99.             return 0L;
  100.  
  101.         case WM_INITMENUPOPUP:
  102.             // Set check marks and enable menu items in popups
  103.             if( !(BOOL) HIWORD( lParam ) &&
  104.                 ( hwndPicture = (HWND) SendMessage
  105.                 ( g.hwndClient, WM_MDIGETACTIVE, 0, 0L )) &&
  106.                 IsWindow( hwndPicture ))
  107.                 SendMessage( hwndPicture,
  108.                 WM_VIEWER_INITPOPUPS, wParam, lParam );
  109.  
  110.             return 0L;
  111.  
  112.         case WM_COMMAND:
  113.             switch( wParam ) {
  114.                 case VIEWER_FILE_OPEN: // file menu popup
  115.                 case VIEWER_FILE_CLOSE:
  116.                 case VIEWER_FILE_PRTSETUP:
  117.                 case VIEWER_FILE_PRINT:
  118.                 case VIEWER_FILE_EXIT:
  119.                     return ViewerFileCommands
  120.                         ( hwndFrame, wParam, HIWORD (lParam));
  121.  
  122.                 case VIEWER_WINDOW_TILE: // window menu popup
  123.                 case VIEWER_WINDOW_CASCADE:
  124.                 case VIEWER_WINDOW_ARRANGE:
  125.                     return ViewerWindowCommands
  126.                         ( hwndFrame, wParam, HIWORD (lParam));
  127.  
  128.  
  129.                 case VIEWER_HELP_VIEWERHELP: // help menu popup
  130.                 case VIEWER_HELP_USINGHELP:
  131.                 case VIEWER_HELP_ABOUTVIEWER:
  132.                     return ViewerHelpCommands
  133.                         ( hwndFrame, wParam, HIWORD (lParam));
  134.  
  135.                 default:
  136.                     if( ( hwndPicture = (HWND) SendMessage
  137.                         ( g.hwndClient, WM_MDIGETACTIVE, 0, 0L )) &&
  138.                         IsWindow( hwndPicture ))
  139.                         SendMessage( hwndPicture,
  140.                         WM_COMMAND, wParam, lParam );
  141.  
  142.                     break; // break to DefFrameProc
  143.             }
  144.  
  145.             break;
  146.  
  147.         // WM_USER messages
  148.  
  149.         case WM_VIEWER_CMDLINE:
  150.             return LaunchPictureWnd( (LPSTR) lParam, NULL );
  151.  
  152.         case WM_VIEWER_PICTUREDELETED:
  153.             // Decrement picture count. This is incremented in LaunchPictureWnd
  154.             // when picture is created
  155.             if( --g.wNumPictures <= 0 )
  156.                 ViewerEnableMenus( hwndFrame, FALSE );
  157.             return 0L;
  158.  
  159.         // These next messages are posted by the ole callback function in PictUtl.c
  160.         case WM_VIEWER_OLE_OPTIONSDLG:
  161.             ViewerGetOptions( NULL, (LPQTOLE_OPTIONSPICTURE) lParam );
  162.             return 0L;
  163.  
  164.         case WM_VIEWER_OLE_PLAYOBJECT:
  165.             QTOLE_PlayObject( ViewerQueryOleData(), lParam );
  166.             return 0L;
  167.  
  168.  
  169.         // end WM_USER messages
  170.  
  171.  
  172.         // Standard drag and drop processing. Allows for multiple pictures but
  173.         // does not worry about position of drop
  174.         case WM_DROPFILES:
  175.             return ProcessDroppedFiles( hwndFrame, wParam );
  176.  
  177.         case WM_QUERYENDSESSION:
  178.         case WM_CLOSE:
  179.             if( g.wNumPictures && 
  180.                 ( lpfnEnumPictures = (WNDENUMPROC) MakeProcInstance
  181.                 ( (FARPROC) CloseEnumProc, ViewerQueryInstance()))) { // Give all pictures a chance to stop the close
  182.                 EnumChildWindows( g.hwndClient, lpfnEnumPictures, 0L );
  183.                 FreeProcInstance( (FARPROC) lpfnEnumPictures );
  184.  
  185.                 // If someone didn't want to close, don't kill the app
  186.                 if( NULL != GetWindow( g.hwndClient, GW_CHILD ))
  187.                     return 0L;
  188.             }
  189.  
  190.             // Tell qtole.dll that we are closing the server
  191.             // Don't close if QTOLE_ClosingServerWnd returns FALSE;
  192.             if( ( lpOleData = ViewerQueryOleData()) && 
  193.                 lpOleData->lpqtoleServer &&
  194.                 !QTOLE_ClosingServerWnd( lpOleData, message ))
  195.                 return 0L;
  196.  
  197.             break; // break to DefFrameProc
  198.  
  199.  
  200.         case WM_NCDESTROY:
  201.             DragAcceptFiles( hwndFrame, FALSE );
  202.  
  203.             // Destroy help instance
  204.             DestroyHelpInstance( hwndFrame );
  205.  
  206.             // NULL the global hwnds in viewmain.c
  207.             ViewerNoMoreWindow();
  208.  
  209.             PostQuitMessage( 0 );
  210.             break;
  211.  
  212.     }
  213.  
  214.     return DefFrameProc
  215.         ( hwndFrame, g.hwndClient, message, wParam, lParam );
  216. }
  217.  
  218.  
  219. // Function: ViewerFrameCreate - process WM_CREATE message
  220. // --------------------------------------------------------------------
  221. // Parameters: HWND hwndFrame;         Frame window
  222. //
  223. // Returns:    0L if OK, else returns -1L to kill app
  224. // --------------------------------------------------------------------
  225. static LONG NEAR ViewerFrameCreate( HWND hwndFrame )
  226.  
  227. {
  228.     CLIENTCREATESTRUCT  clientcreate;  // MDI client create struct
  229.     char                szCaption[50]; // caption buffer;
  230.  
  231.  
  232.     szCaption[0] = '\0';
  233.     if( LoadString( ViewerQueryResources(), VIEWER_STRING_CAPTION,
  234.         szCaption, sizeof( szCaption )))
  235.         SetWindowText( hwndFrame, szCaption );
  236.     // No point in trying for an error message here since it probably won't
  237.     // load either.
  238.  
  239.     // disable menu items until a picture is created
  240.     g.wNumPictures = 0;
  241.     ViewerEnableMenus( hwndFrame, FALSE );
  242.  
  243.     DragAcceptFiles( hwndFrame, TRUE );
  244.  
  245.     clientcreate.hWindowMenu =
  246.         GetSubMenu( GetMenu( hwndFrame ), MENU_WINDOW_POS );
  247.     clientcreate.idFirstChild = VIEWER_CLIENT_FIRSTCHILD;
  248.  
  249.     if( !(g.hwndClient = CreateWindow( "MDICLIENT", NULL,
  250.         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE |
  251.         WS_HSCROLL | WS_VSCROLL ,
  252.         0, 0, 0, 0, hwndFrame, ( HMENU) 1,
  253.         ViewerQueryInstance(), (LPVOID) &clientcreate )))
  254.         return -1L; // return -1 to kill app
  255.     else
  256.         return  0L;
  257. }
  258.  
  259.  
  260. // Function: ViewerFileCommands - Process WM_COMMAND, File popup messages
  261. // --------------------------------------------------------------------
  262. // Parameters: HWND   hwndFrame;      Frame window
  263. //             WORD   wIDItem;        Menu or control id
  264. //             WORD   wNotifyCode;    notification message
  265. //
  266. // Returns:    LONG   generally 0L
  267. // --------------------------------------------------------------------
  268. static LONG NEAR ViewerFileCommands
  269.                     (HWND hwndFrame, WPARAM wIDItem, WORD wNotifyCode )
  270.  
  271. {
  272.     HWND          hwndPicture;                 // Handle of picture window
  273.     OPENFILENAME  ofn;                         // OPENFILENAME struct
  274.     UINT          cbString;                    // Length of filter string
  275.     char          szPicturePath[MAX_PATH_LEN]; // Picture file path.
  276.                                                // Must be at least 256 bytes
  277.     char          szPictureName[MAX_NAME_LEN]; // Picture file name
  278.     char          szFilter[MAX_PATH_LEN];      // Picture file filter str
  279.     LPSTR         lpTemp;                      // Temp -> to string
  280.     LPSTR         lpSave;                      // Temp -> to string
  281.     char          chReplace;                   // String separator used in filter string
  282.     DWORD         dwError;                     // Common dlg error return
  283.     PRINTDLG      pd;                          // Print common dlg struct
  284.     ABORTPROC     lpPrintAbortProc;            // -> to Print abort proc
  285.     DLGPROC       lpPrtCancelProc;             // -> to Print cancel dlg proc
  286.     WORD          wIDError;                    // Resource error string id
  287.     int           nError;                      // Error return
  288.  
  289.     static DWORD  dwFilterIndex = 1; // Filter index. Saved between 
  290.                                      // invocations of dialog
  291.  
  292.     typedef UINT ( CALLBACK * PRINTDLGHOOKPROC ) (HWND, UINT, WPARAM, LPARAM );
  293.  
  294.  
  295.     switch( wIDItem ) {
  296.         case VIEWER_FILE_OPEN:
  297.             memset( &ofn, 0, sizeof( OPENFILENAME ));
  298.             szPicturePath[0] = '\0';
  299.  
  300.             if( !(cbString = LoadString( ViewerQueryResources(),
  301.                 VIEWER_STRING_OPENPICTFILTER,
  302.                 szFilter, sizeof( szFilter ))))
  303.                 return 0L;
  304.  
  305.             // See 3.1 SDK manuals, vol 1 for examples of common dlg processing
  306.             lpTemp = szFilter + lstrlen( szFilter );
  307.             chReplace = *AnsiPrev( szFilter, lpTemp );
  308.             lpTemp = szFilter;
  309.             while( *lpTemp ) {
  310.                 if( *lpTemp == chReplace ) { // Need to increment pointer past chReplace before
  311.                                              // setting to NULL. Otherwise AnsiNext thinks it is
  312.                                              // at end of string and quits
  313.                     lpSave = lpTemp;
  314.                     lpTemp = AnsiNext( lpTemp );
  315.                     *lpSave = '\0';
  316.                 }
  317.                 else
  318.                     lpTemp = AnsiNext( lpTemp );
  319.             }
  320.  
  321.             ofn.lStructSize    = sizeof( OPENFILENAME );
  322.             ofn.hwndOwner      = hwndFrame;
  323.             ofn.lpstrFilter    = szFilter;
  324.             ofn.nFilterIndex   = dwFilterIndex;
  325.             ofn.lpstrFile      = szPicturePath;
  326.             ofn.nMaxFile       = sizeof( szPicturePath );
  327.             ofn.lpstrFileTitle = szPictureName;
  328.             ofn.nMaxFileTitle  = sizeof( szPictureName );
  329.             ofn.Flags =
  330.                 OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  331.  
  332.             if( GetOpenFileName( &ofn )) { // Save the current filter index
  333.                 dwFilterIndex = ofn.nFilterIndex;
  334.                 LaunchPictureWnd( szPicturePath, szPictureName );
  335.             }
  336.             else if( dwError = CommDlgExtendedError()) { // Tell the user about the error
  337.                 TellUserCommonDlgError( dwError );
  338.             }
  339.  
  340.             return 0L;
  341.  
  342.         case VIEWER_FILE_CLOSE:
  343.             if( ( hwndPicture = (HWND) SendMessage
  344.                 ( g.hwndClient, WM_MDIGETACTIVE, 0, 0L )) &&
  345.                 IsWindow( hwndPicture ))
  346.                 SendMessage( hwndPicture, WM_CLOSE, 0, 0L );
  347.  
  348.             return 0L;
  349.  
  350.         case VIEWER_FILE_PRTSETUP:
  351.             memset( &pd, 0, sizeof( PRINTDLG ));
  352.  
  353.             pd.lStructSize = sizeof( PRINTDLG );
  354.             pd.hwndOwner   = hwndFrame;
  355.             pd.Flags       = PD_PRINTSETUP;
  356.  
  357.             if( ( PrintDlg( &pd ) == 0 ) &&
  358.                 ( dwError = CommDlgExtendedError())) { // Tell the user about the error
  359.                 TellUserCommonDlgError( dwError );
  360.             }
  361.  
  362.             return 0L;
  363.  
  364.         case VIEWER_FILE_PRINT:
  365.             // Customize the common dlg to eliminate some options that are 
  366.             // not useful. This requires a new template and a hook proc
  367.             memset( &pd, 0, sizeof( PRINTDLG ));
  368.  
  369.             pd.lStructSize = sizeof( PRINTDLG );
  370.             pd.hwndOwner   = hwndFrame;
  371.             pd.Flags       = PD_RETURNDC |
  372.                 PD_ENABLEPRINTHOOK | PD_ENABLEPRINTTEMPLATE;
  373.             pd.hInstance   = ViewerQueryResources();
  374.             pd.lpPrintTemplateName = MAKEINTRESOURCE( CUSTOM_DLG_COMN_PRINT );
  375.             if( !( pd.lpfnPrintHook =  (PRINTDLGHOOKPROC) 
  376.                 MakeProcInstance( (FARPROC) PrintDlgHookProc,
  377.                 ViewerQueryInstance()))) {
  378.                 CommonTellUser( ViewerQueryResources(), 
  379.                     VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  380.                 return 0L;
  381.             }
  382.  
  383.             if( PrintDlg( &pd ) != 0 ) {
  384.                 lpPrtCancelProc = (DLGPROC) MakeProcInstance
  385.                     ( (FARPROC) PrintCancelDlgProc, ViewerQueryInstance() );
  386.  
  387.                 lpPrintAbortProc = (ABORTPROC) MakeProcInstance
  388.                     ( (FARPROC) PrintAbortProc, ViewerQueryInstance() );
  389.  
  390.                 if( !lpPrtCancelProc || !lpPrintAbortProc ) {
  391.                     CommonTellUser( ViewerQueryResources(), 
  392.                         VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  393.                     return 0L;
  394.                 }
  395.  
  396.                 g.bUserAbortPrint = FALSE;
  397.                 nError   = 0;
  398.                 wIDError = 0;
  399.  
  400.                 if( !(g.hwndCancelPrt =
  401.                     CreateDialog( ViewerQueryResources(),
  402.                     MAKEINTRESOURCE( VIEWER_DLG_PRINTCANCEL ),
  403.                     hwndFrame, lpPrtCancelProc ))) {
  404.                     wIDError = VIEWER_STRING_CANCELDLG;
  405.                 }
  406.                 else {
  407.                     EnableWindow( hwndFrame, FALSE ); // disable frame window
  408.  
  409.                     if( SetAbortProc( pd.hDC, lpPrintAbortProc ) <= 0 )
  410.                         wIDError = VIEWER_STRING_ABORTPROC;
  411.                     else {
  412.                         if( hwndPicture = (HWND) SendMessage
  413.                             ( g.hwndClient, WM_MDIGETACTIVE, 0, 0L ))
  414.                             nError = (int) SendMessage( hwndPicture,
  415.                             WM_VIEWER_PRINTPICTURE, 0,
  416.                             (LPARAM) (LPPRINTDLG) &pd );
  417.                         if( ( nError < 0 ) &&
  418.                             ( nError & SP_NOTREPORTED ) &&
  419.                             !g.bUserAbortPrint ) {
  420.                             switch( nError ) {
  421.                                 case SP_APPABORT:
  422.                                 case SP_USERABORT:
  423.                                     break;
  424.                                 case SP_OUTOFDISK:
  425.                                     wIDError = VIEWER_STRING_PRT_OUTOFDISK;
  426.                                     break;
  427.                                 case SP_OUTOFMEMORY:
  428.                                     wIDError = VIEWER_STRING_PRT_NOMEMORY;
  429.                                     break;
  430.                                 case SP_ERROR: // fall through
  431.                                 default:
  432.                                     wIDError = VIEWER_STRING_PRT_GENERROR;
  433.                                     break;
  434.                             }
  435.                         }
  436.                     }
  437.  
  438.                     // reenable frame window
  439.                     EnableWindow( hwndFrame, TRUE ); 
  440.  
  441.                     if( g.hwndCancelPrt )
  442.                         DestroyWindow( g.hwndCancelPrt );
  443.                 }
  444.  
  445.                 if( wIDError )
  446.                     CommonTellUser( ViewerQueryResources(), wIDError,
  447.                     VIEWER_STRING_PRT_CAPTION, MB_OK );
  448.  
  449.                 FreeProcInstance( (FARPROC) lpPrtCancelProc );
  450.                 FreeProcInstance( (FARPROC) lpPrintAbortProc );
  451.  
  452.                 if( pd.hDC )
  453.                     DeleteDC( pd.hDC );
  454.                 if( pd.hDevMode != NULL )
  455.                     GlobalFree( pd.hDevMode );
  456.                 if( pd.hDevNames != NULL )
  457.                     GlobalFree( pd.hDevNames );
  458.             }
  459.             else if( dwError = CommDlgExtendedError()) { // Tell the user about the error
  460.                 TellUserCommonDlgError( dwError );
  461.             }
  462.  
  463.             return 0L;
  464.  
  465.         case VIEWER_FILE_EXIT:
  466.             SendMessage( hwndFrame, WM_CLOSE, 0, 0L );
  467.             return 0L;
  468.     }
  469.  
  470.     return 0L; // should never get here
  471.  
  472. }
  473.  
  474.  
  475. // Function: ViewerWindowCommands - Process WM_COMMAND, Window popup messages
  476. // --------------------------------------------------------------------
  477. // Parameters: HWND   hwndFrame;      Frame window
  478. //             WORD   wIDItem;        Menu or control id
  479. //             WORD   wNotifyCode;    notification message
  480. //
  481. // Returns:    LONG   generally 0L
  482. // --------------------------------------------------------------------
  483. static LONG NEAR ViewerWindowCommands
  484.                     (HWND hwndFrame, WPARAM wIDItem, WORD wNotifyCode )
  485.  
  486. // This is standard MDI stuff. 
  487. {
  488.     switch( wIDItem ) {
  489.         case VIEWER_WINDOW_TILE:
  490.             SendMessage( g.hwndClient, WM_MDITILE, 0, 0L );
  491.             return 0L;
  492.  
  493.         case VIEWER_WINDOW_CASCADE:
  494.             SendMessage( g.hwndClient, WM_MDICASCADE, 0, 0L );
  495.             return 0L;
  496.  
  497.         case VIEWER_WINDOW_ARRANGE:
  498.             SendMessage( g.hwndClient, WM_MDIICONARRANGE, 0, 0L );
  499.             return 0L;
  500.     }
  501.  
  502.     return 0L; // should never get here
  503.  
  504. }
  505.  
  506.  
  507. // Function: ViewerHelpCommands - Process WM_COMMAND, Help popup messages
  508. // --------------------------------------------------------------------
  509. // Parameters: HWND   hwndFrame;      Frame window
  510. //             WORD   wIDItem;        Menu or control id
  511. //             WORD   wNotifyCode;    notification message
  512. //
  513. // Returns:    LONG   generally 0L
  514. // --------------------------------------------------------------------
  515. static LONG NEAR ViewerHelpCommands
  516.                     (HWND hwndFrame, WPARAM wIDItem, WORD wNotifyCode )
  517.  
  518. {
  519.     char       szHelp[MAX_PATH_LEN]; // Help file path
  520.     DLGPROC    lpDlgProc;            // -> dialog proc
  521.  
  522.     switch( wIDItem ) {
  523.         case VIEWER_HELP_VIEWERHELP:
  524.             CommonGetLocalizedHelpFile
  525.                 ( VIEWER_ROOT_NAME, szHelp, ViewerQueryInstance() );
  526.  
  527.             if( szHelp[0] )
  528.                 WinHelp( hwndFrame, (LPCSTR) szHelp, HELP_CONTENTS, 0L );
  529.             else
  530.                 CommonTellUser( ViewerQueryResources(),
  531.                 VIEWER_STRING_NOHELPFILE,
  532.                 VIEWER_STRING_CAPTION, MB_OK );
  533.  
  534.             return 0L;
  535.  
  536.         case VIEWER_HELP_USINGHELP:
  537.             WinHelp( hwndFrame, (LPCSTR) "WINHELP.HLP", HELP_CONTENTS, 0L );
  538.             return 0L;
  539.  
  540.         case VIEWER_HELP_ABOUTVIEWER:
  541.             if( ( g.hAboutBitmap = LoadBitmap( ViewerQueryResources(),
  542.                 MAKEINTRESOURCE( VIEWER_VIEWER_BITMAP ))) &&
  543.                 ( lpDlgProc = (DLGPROC) MakeProcInstance
  544.                 ( (FARPROC) AboutDlgProc, ViewerQueryInstance()))) {
  545.                 DialogBox( ViewerQueryResources(),
  546.                     MAKEINTRESOURCE( VIEWER_DLG_ABOUTVIEWER ),
  547.                     hwndFrame, lpDlgProc );
  548.                 FreeProcInstance( (FARPROC) lpDlgProc );
  549.             }
  550.             else
  551.                 CommonTellUser( ViewerQueryResources(),
  552.                 VIEWER_STRING_NOMEMORY,
  553.                 VIEWER_STRING_CAPTION, MB_OK );
  554.             if( g.hAboutBitmap )
  555.                 DeleteObject( g.hAboutBitmap );
  556.             g.hAboutBitmap = NULL;
  557.  
  558.             return 0L;
  559.     }
  560.  
  561.     return 0L; // should never get here
  562.  
  563. }
  564.  
  565.  
  566. // Function: CloseEnumProc - Close all enumerate proc
  567. // --------------------------------------------------------------------
  568. // Parameters: As required by Microsoft Windows
  569. //
  570. // Returns:    Always TRUE to enumerate all windows
  571. // --------------------------------------------------------------------
  572. BOOL __export CALLBACK CloseEnumProc( HWND hwnd, LPARAM lParam )
  573.  
  574. {
  575.     char    szClassName[40]; // Temp buffer for class name
  576.  
  577.     // Check class name since there are several classes of child windows
  578.     // These include scroll bars etc that appear in picture windows
  579.     if( !GetClassName( hwnd, szClassName, sizeof( szClassName )) ||
  580.         lstrcmpi( szClassName, VIEWER_PICTURE_CLASS ))
  581.         return TRUE;
  582.  
  583.     // If someone doesn't want to quit, stop enumeration
  584.     if( !SendMessage( hwnd, WM_QUERYENDSESSION, 0, 0L ))
  585.         return FALSE;
  586.  
  587.     SendMessage( GetParent( hwnd ), WM_MDIDESTROY, (WPARAM) hwnd, 0L );
  588.  
  589.     return TRUE;
  590. }
  591.  
  592. // Function: PaletteEnumProc - Tells all child wnds to repaint because
  593. //                             of palette change
  594. // --------------------------------------------------------------------
  595. // Parameters: As required by Microsoft Windows
  596. //
  597. // Returns:    Always TRUE to enumerate all windows
  598. // --------------------------------------------------------------------
  599. BOOL __export CALLBACK PaletteEnumProc( HWND hwnd, LPARAM lParam )
  600.  
  601. {
  602.     char    szClassName[40]; // Temp buffer for class name
  603.  
  604.     // Check class name since there are several classes of child windows
  605.     // These include scroll bars etc that appear in picture windows
  606.     if( !GetClassName( hwnd, szClassName, sizeof( szClassName )) ||
  607.         lstrcmpi( szClassName, VIEWER_PICTURE_CLASS ))
  608.         return TRUE;
  609.  
  610.     if( hwnd != (HWND) LOWORD( lParam ))
  611.         InvalidateRect( hwnd, NULL, FALSE );
  612.  
  613.     return TRUE;
  614. }
  615.  
  616.  
  617. // Function: LaunchPictureWnd - tell hwndClient to launch a picture wnd
  618. // --------------------------------------------------------------------
  619. // Parameters: LPSTR    lpPicturePath        Path of picture file
  620. //             LPSTR    lpName               File name of picture
  621. //
  622. // Returns:    LONG     generally 0L
  623. // --------------------------------------------------------------------
  624. static LONG NEAR LaunchPictureWnd( LPSTR lpPicturePath, LPSTR lpName )
  625.  
  626. {
  627.     MDICREATESTRUCT       mdicreate;   // mdi create struct
  628.     HWND                  hwndPicture; // Temp handle of window
  629.  
  630.     if( !lpPicturePath[0] )
  631.         return -1L;
  632.  
  633.     if( lpName == NULL ) {
  634.         lpName = lpPicturePath + lstrlen( lpPicturePath );
  635.         lpName = AnsiPrev( lpPicturePath, lpName );
  636.         while( *lpName && (*lpName != '\\') && (lpName != lpPicturePath))
  637.             lpName = AnsiPrev( lpPicturePath, lpName );
  638.         if( *lpName == '\\' )
  639.             lpName = AnsiNext( lpName );
  640.     }
  641.  
  642.     mdicreate.szClass = VIEWER_PICTURE_CLASS;
  643.     mdicreate.szTitle = lpName;
  644.     mdicreate.hOwner  = ViewerQueryInstance();
  645.     mdicreate.x       = CW_USEDEFAULT;
  646.     mdicreate.y       = CW_USEDEFAULT;
  647.     mdicreate.cx      = CW_USEDEFAULT;
  648.     mdicreate.cy      = CW_USEDEFAULT;
  649.     mdicreate.style   = MDIS_ALLCHILDSTYLES | WS_CLIPCHILDREN;
  650.     mdicreate.lParam  = (LPARAM) lpPicturePath;
  651.  
  652.     if( !( hwndPicture = (HWND) SendMessage
  653.         ( g.hwndClient, WM_MDICREATE, 0,
  654.         (LPARAM) (LPMDICREATESTRUCT) &mdicreate ))) {
  655.         return -1L;
  656.     }
  657.     else {
  658.         if(++g.wNumPictures == 1 )
  659.             ViewerEnableMenus( ViewerQueryFrameWindow(), TRUE );
  660.  
  661.         return 0L;
  662.     }
  663. }
  664.  
  665.  
  666. // Function: ProcessDroppedFiles - Process the WM_DROPFILES message
  667. // --------------------------------------------------------------------
  668. // Parameters: HWND     hwndFrame         Frame window handle
  669. //             WPARAM   wParam            Message wParam
  670. //
  671. // Returns:    LONG     Always 0L;
  672. // --------------------------------------------------------------------
  673. static LONG NEAR ProcessDroppedFiles( HWND hwndFrame, WPARAM wParam )
  674.  
  675. {
  676.     int           i;                        // Temp counter
  677.     int           nNumFiles;                // Temp number of dropped files
  678.     UINT          uBytes;                   // Temp len of drop file path
  679.     char          szDropFile[MAX_PATH_LEN]; // Temp drop file path
  680.  
  681.     if( nNumFiles = DragQueryFile( (HDROP) wParam, 0xffff,
  682.         (LPSTR) NULL, 0 )) { // Create processing requires that frame window has
  683.                              // nonzero dimensions so first restore iconic window
  684.         if( IsIconic( hwndFrame ))
  685.             ShowWindow( hwndFrame, SW_SHOWNORMAL );
  686.  
  687.         for( i=0; i < nNumFiles; i++ ) {
  688.             uBytes = DragQueryFile( (HDROP) wParam, i,
  689.                 (LPSTR) szDropFile, sizeof( szDropFile ));
  690.             if( uBytes > 0 )
  691.                 LaunchPictureWnd( szDropFile, NULL );
  692.         }
  693.     }
  694.  
  695.     DragFinish( (HDROP) wParam );
  696.  
  697.     return 0L;
  698. }
  699.  
  700. // Function: DestroyHelpInstance - Tell windows that instance is done with
  701. //                                 help. This is called as a function so that
  702. //                                 szHelp[] is not an automatic var. in the
  703. //                                 winproc
  704. // --------------------------------------------------------------------
  705. // Parameters: HWND     hwndFrame         Frame window handle
  706. //
  707. // Returns:    VOID
  708. // --------------------------------------------------------------------
  709. static VOID NEAR DestroyHelpInstance( HWND hwndFrame )
  710.  
  711. {
  712.     char          szHelp[MAX_PATH_LEN]; // Help file name
  713.  
  714.     WinHelp( hwndFrame, CommonGetLocalizedHelpFile
  715.         ( VIEWER_ROOT_NAME, szHelp, ViewerQueryResources() ),
  716.         HELP_QUIT, NULL );
  717.     return;
  718. }
  719.  
  720. // Function: AboutDlgProc - About dialog proc
  721. // --------------------------------------------------------------------
  722. // Parameters: As required by Microsoft Windows
  723. //
  724. // Returns:    As required by Microsoft Windows
  725. // --------------------------------------------------------------------
  726. BOOL __export CALLBACK AboutDlgProc
  727.     ( HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam )
  728.  
  729. {
  730.     BITMAP       bm;          // Temp bitmap struct
  731.     HWND         hwndCntrl;   // Handle of rect control that is painted
  732.                               // over with bitmap
  733.     HDC          hdestDC;     // hdc of control rect
  734.     HDC          hmemDC;      // Memory dc
  735.     RECT         rcdestRect;  // Rect of control
  736.     HBITMAP      hbitmapSave; // return from select object
  737.     PAINTSTRUCT  ps;          // Paint struct
  738.  
  739.  
  740.     switch( msg ) {
  741.         case WM_COMMAND:
  742.             EndDialog( hdlg, 0 );
  743.             return TRUE;
  744.  
  745.         case WM_PAINT:
  746.             // Don't bother with error messages since only effect is that
  747.             // bitmap will not appear in dialog
  748.             if( !BeginPaint( hdlg, &ps ))
  749.                 return FALSE;
  750.             EndPaint( hdlg, &ps );
  751.  
  752.             if( !g.hAboutBitmap || 
  753.                 !( hwndCntrl = GetDlgItem( hdlg, VIEWER_ABOUT_BMPFRAME )))
  754.                 return FALSE;
  755.  
  756.             InvalidateRect( hwndCntrl, NULL, TRUE );
  757.             UpdateWindow( hwndCntrl );
  758.  
  759.             if( !(hdestDC = GetDC( hwndCntrl )))
  760.                 return FALSE;
  761.  
  762.             if( hmemDC = CreateCompatibleDC( hdestDC )) {
  763.                 if( hbitmapSave = SelectObject( hmemDC, g.hAboutBitmap )) {
  764.                     GetObject( g.hAboutBitmap, sizeof( BITMAP ), &bm );
  765.                     GetClientRect( hwndCntrl, &rcdestRect );
  766.  
  767.                     BitBlt( hdestDC, 
  768.                         ( rcdestRect.right - bm.bmWidth ) / 2,
  769.                         ( rcdestRect.bottom - bm.bmHeight ) / 2, 
  770.                         bm.bmWidth, bm.bmHeight, hmemDC, 0, 0, SRCCOPY );
  771.  
  772.                     SelectObject( hmemDC, hbitmapSave );
  773.                 }
  774.  
  775.                 DeleteDC( hmemDC );
  776.             }
  777.  
  778.             ReleaseDC( hwndCntrl, hdestDC );
  779.  
  780.             return FALSE;
  781.  
  782.         default:
  783.             return FALSE;
  784.     }
  785.  
  786.     return FALSE;
  787. }
  788.  
  789.  
  790. // Function: PrintAbortProc - Print abort proc
  791. // --------------------------------------------------------------------
  792. // Parameters: As required by Microsoft Windows
  793. //
  794. // Returns:    As required by Microsoft Windows
  795. // --------------------------------------------------------------------
  796. int __export CALLBACK PrintAbortProc( HDC hdc, int nCode )
  797.  
  798. {
  799.     MSG     msg; // Message struct
  800.  
  801.     while( !g.bUserAbortPrint &&
  802.         PeekMessage( &msg, NULL, NULL, NULL, PM_REMOVE )) {
  803.         if( !g.hwndCancelPrt || !IsDialogMessage( g.hwndCancelPrt, &msg )) {
  804.             TranslateMessage( &msg );
  805.             DispatchMessage( &msg );
  806.         }
  807.     }
  808.  
  809.     return !g.bUserAbortPrint;
  810. }
  811.  
  812. // Function: PrintCancelDlgProc - User cancel printing dlg proc
  813. // --------------------------------------------------------------------
  814. // Parameters: As required by Microsoft Windows
  815. //
  816. // Returns:    As required by Microsoft Windows
  817. // --------------------------------------------------------------------
  818. BOOL __export CALLBACK PrintCancelDlgProc
  819.     ( HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam )
  820.  
  821. {
  822.     char    szName[50]; // Buffer for picture name
  823.  
  824.     switch( msg ) {
  825.         case WM_INITDIALOG:
  826.             SetFocus( GetDlgItem( hdlg, IDCANCEL ));
  827.             SetDlgItemText( hdlg, PRINT_CANCEL_PICTURENAME,
  828.                 ViewerQueryActivePictureName( szName ));
  829.             return TRUE;
  830.  
  831.         case WM_COMMAND:
  832.             return ( g.bUserAbortPrint = TRUE );
  833.  
  834.         case WM_DESTROY:
  835.             g.hwndCancelPrt = NULL;
  836.             break;
  837.     }
  838.  
  839.     return FALSE;
  840. }
  841.  
  842.  
  843. // Function: PrintDlgHookProc - Custom print common dlg hook function
  844. // --------------------------------------------------------------------
  845. // Parameters: As required by Microsoft Windows
  846. //
  847. // Returns:    As required by Microsoft Windows
  848. // --------------------------------------------------------------------
  849. UINT __export CALLBACK PrintDlgHookProc
  850.                 (HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam )
  851.  
  852. { // The dialog ids are defined in dlgs.h
  853.   // Array of ids of controls to be hidden
  854.     static int nIDs[] = {grp1, rad1, rad2, rad3, stc2, edt1, 
  855.                          stc3, edt2, chx1, chx2, pshHelp };
  856.     UINT   i; // Temp counter
  857.  
  858.     if( message == WM_INITDIALOG ) {
  859.         for( i=0; i < ( sizeof( nIDs ) / sizeof( nIDs[0] )); i++ )
  860.             ShowWindow( GetDlgItem( hdlg, nIDs[i] ), SW_HIDE );
  861.  
  862.         return TRUE;
  863.     }
  864.     else
  865.         return FALSE;
  866. }
  867.  
  868.  
  869. // Function: ViewerEnableMenus - Disables menu items when there
  870. //                               are no pictures
  871. // --------------------------------------------------------------------
  872. // Parameters: HWND       hwndFrame      Handle of frame window
  873. //             BOOL       bEnable        Enabling flag
  874. //
  875. // Returns:    VOID
  876. // --------------------------------------------------------------------
  877. static VOID NEAR ViewerEnableMenus( HWND hwndFrame, BOOL bEnable )
  878.  
  879. {
  880.     UINT    fFlag;      // Temp enabling flag
  881.     HMENU   hmenuFrame; // Handle to main menu of frame window
  882.     UINT    i;          // Index
  883.  
  884.     static UINT uMenuIDs[] = {VIEWER_FILE_CLOSE,
  885.                               VIEWER_FILE_PRINT,
  886.  
  887.                               VIEWER_EDIT_COPYPICTURE,
  888.                               VIEWER_EDIT_OPTIONS,
  889.                               VIEWER_EDIT_CANCELSEL,
  890.  
  891.                               VIEWER_IMAGE_GETINFO,
  892.                               VIEWER_IMAGE_HALFSIZE,
  893.                               VIEWER_IMAGE_NORMALSIZE,
  894.                               VIEWER_IMAGE_DOUBLESIZE,
  895.  
  896.                               VIEWER_WINDOW_TILE,
  897.                               VIEWER_WINDOW_CASCADE,
  898.                               VIEWER_WINDOW_ARRANGE
  899.                              };
  900.  
  901.     if( !( hmenuFrame = GetMenu( hwndFrame )))
  902.         return;
  903.  
  904.     fFlag = (bEnable ? MF_ENABLED : MF_GRAYED ) | MF_BYCOMMAND;
  905.     for( i=0; i < sizeof( uMenuIDs ) / sizeof( uMenuIDs[0] ); i++ )
  906.         EnableMenuItem( hmenuFrame, uMenuIDs[i], fFlag );
  907.  
  908.     DrawMenuBar( hwndFrame );
  909.  
  910.     return;
  911. }
  912.  
  913.  
  914. // Function: TellUserCommonDlgError - Tell the user about the common dlg
  915. //                                    error
  916. // --------------------------------------------------------------------
  917. // Parameters: DWORD       dwError      error code returned by common dlg
  918. //
  919. // Returns:    VOID
  920. // --------------------------------------------------------------------
  921. static VOID NEAR TellUserCommonDlgError( DWORD dwError )
  922.  
  923. {
  924.     WORD          wIDErrorString; // String id
  925.  
  926.     // Not much here now, can make this as explicit as desired
  927.     // Now returns text of error id, i.e. "CDERR_INITIALIZATION"
  928.     // Not all messages are explicitly included
  929.  
  930.     switch( dwError ) {
  931.         case CDERR_FINDRESFAILURE: 
  932.             wIDErrorString = VIEWER_STRING_CDLG_FINDRESFAIL;
  933.             break;
  934.         case CDERR_INITIALIZATION:
  935.             wIDErrorString = VIEWER_STRING_CDLG_INITFAIL;
  936.             break;
  937.         case CDERR_LOADRESFAILURE:
  938.             wIDErrorString = VIEWER_STRING_CDLG_LOADRESFAIL;
  939.             break;
  940.         case CDERR_LOCKRESFAILURE:
  941.             wIDErrorString = VIEWER_STRING_CDLG_LOCKRESFAIL;
  942.             break;
  943.         case CDERR_MEMALLOCFAILURE:
  944.             wIDErrorString = VIEWER_STRING_CDLG_MEMALLOCFAIL;
  945.             break;
  946.         case CDERR_MEMLOCKFAILURE:
  947.             wIDErrorString = VIEWER_STRING_CDLG_MEMLOCKFAIL;
  948.             break;
  949.         case CDERR_STRUCTSIZE:
  950.             wIDErrorString = VIEWER_STRING_CDLG_STRUCTSIZE;
  951.             break;
  952.         case FNERR_INVALIDFILENAME:
  953.             wIDErrorString = VIEWER_STRING_CDLG_BADFILENAME;
  954.             break;
  955.         case PDERR_INITFAILURE:
  956.             wIDErrorString = VIEWER_STRING_CDLG_PRTINITFAIL;
  957.             break;
  958.         case PDERR_LOADDRVFAILURE:
  959.             wIDErrorString = VIEWER_STRING_CDLG_LOADDRVFAIL;
  960.             break;
  961.         case PDERR_NODEFAULTPRN:
  962.             wIDErrorString = VIEWER_STRING_CDLG_NODEFPRINTER;
  963.             break;
  964.         case PDERR_NODEVICES:
  965.             wIDErrorString = VIEWER_STRING_CDLG_NODEVICES;
  966.             break;
  967.         case PDERR_PRINTERNOTFOUND:
  968.             wIDErrorString = VIEWER_STRING_CDLG_NOFINDPNTR;
  969.             break;
  970.         case PDERR_SETUPFAILURE:
  971.             wIDErrorString = VIEWER_STRING_CDLG_SETUPFAIL;
  972.             break;
  973.         default:
  974.             wIDErrorString = VIEWER_STRING_CDLG_GENFAILURE;
  975.             break;
  976.     }
  977.  
  978.     if( wIDErrorString == VIEWER_STRING_CDLG_GENFAILURE )
  979.         CommonTellUser( ViewerQueryResources(),
  980.         VIEWER_STRING_CDLG_GENFAILURE,
  981.         VIEWER_STRING_CDLG_CAP, MB_OK, dwError );
  982.     else
  983.         CommonTellUser( ViewerQueryResources(),
  984.         VIEWER_STRING_CDLG_FORMAT, VIEWER_STRING_CDLG_CAP,
  985.         MB_OK, wIDErrorString );
  986.     return;
  987.  
  988. }
  989.  
  990.  
  991. //  The remaining functions are the query functions called by other modules
  992.  
  993. // Function: ViewerQueryClientWindow - Query Client Window Handle
  994. // --------------------------------------------------------------------
  995. // Parameters: None.
  996. //
  997. // Returns:    HWND g.hwndClient;        MDI client window handle
  998. // --------------------------------------------------------------------
  999. HWND FAR ViewerQueryClientWindow( VOID )
  1000.  
  1001. {
  1002.     return g.hwndClient;
  1003. }
  1004.  
  1005. // Function: ViewerQueryNumPictures - Query number of pictures
  1006. // --------------------------------------------------------------------
  1007. // Parameters: None.
  1008. //
  1009. // Returns:    HWND g.wNumPictures;    Number of pictures
  1010. // --------------------------------------------------------------------
  1011. WORD FAR ViewerQueryNumPictures( VOID )
  1012.  
  1013. {
  1014.     return g.wNumPictures;
  1015. }
  1016.